/*
-----------------------------------------------------------------------------
This source file is part of DIVA
The project of Engineering Lab, dept. of CSIE, NTNU.

Copyright (c) 2000-2006 The Software Engineering Lab, dept. of CSIE, NTNU.
-----------------------------------------------------------------------------
Filename:    DIVA_Manager.h
Description: keep all the vms rendered on the screen.


-----------------------------------------------------------------------------
*/
/*------------------------------------------------------------*/
#ifndef _DIVA_Manager_H_
#define	_DIVA_Manager_H_
/*------------------------------------------------------------*/

#include <string>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>

#include "Ogre.h"
#include "lock.h"
class DIVA_VM;



//using namespace Ogre;

class DIVA_Manager{
private:
	static DIVA_Manager *DM;
    Ogre::SceneNode * _parentnode ;
	bool _animationonoff ;
	Mutex _animation_mutex ;
	Lock* _lock ;

	/// constructor
	DIVA_Manager(Ogre::SceneManager* );

	/// vector saves all the vm on the screen
	std::vector<DIVA_VM* > all_VM_List;

	// map saves all the pair of vm and entity, so that when a entity is clicked
	// we can trace back which VM it is associated with
	std::map<Ogre::MovableObject*,DIVA_VM*> vm_MovableObject_Table;

	/// vector tor hitting 
	std::vector<Ogre::MovableObject*> hitting_objs;

	/// scene manager
	Ogre::SceneManager* _SceneMgr;
	Ogre::Camera * _Camera ;

	/// ray scene query - used for do the second query
	Ogre::RaySceneQuery* mRaySceneQuery;

	/** VM that register to listen VMAnimation() event */
	std::vector<DIVA_VM *> _animation_list ;
	///當有VM的 constructor 要 addVMAnimationListener 時先暫時加到這一個 temp 的vector 中
	std::vector<DIVA_VM *> _temp_anim_add ;
	/// removeVMAnimationListener 時先暫時加到這一個 temp 的vector 中
	std::vector<DIVA_VM *> _temp_anim_remove;

	
	
public:

	/// initial method 
	static void init(Ogre::SceneManager*);

	/// singletom method
	static DIVA_Manager* getInstance();

	/// destructor
	~DIVA_Manager();

	/// bool remove(DIVA_VM* ); -看來存vm的list應該用map來作會比較好作 ，因為若是要刪除特定的vm話 ，用map來搜尋會比較快
	bool add(DIVA_VM* );
	
	/// get the list saved all the vm
	std::vector<DIVA_VM*> get_all_VM_List();

	/// call all the draw of vm in the list
	bool update_all_VM_List();

	/// converting string to any type
	template <class T>
    bool from_string(T& t, const std::string& s, std::ios_base& (*f)(std::ios_base&))
    {
		std::istringstream iss(s);
		return !(iss >> f >> t).fail();
	}

	/// method for user to get the vm entity table
	std::map<Ogre::MovableObject*, DIVA_VM*> *get_vm_MovableObject_Table();

	/// method for query the entity from vm or query vm from entity by the table vmEntityTable
	DIVA_VM* get_VM_from_MovableObject(Ogre::MovableObject* );
	Ogre::MovableObject* get_MovableObject_from_VM(DIVA_VM* );

	/// method for getting the scene manager
	Ogre::SceneManager* getSceneManager();

	/// method for doing second times ray scene query 
	void ray_scene_query(Ogre::Real x, Ogre::Real y);

	/** method for poping the vm selected by ray */
	DIVA_VM* pop_front_hitting_VM();

	/** register one relation between the movable object and diva vm into the map "vm_MovableObject_Table" */
	void reg_MovableObj_VM_relation(Ogre::MovableObject*,DIVA_VM*);

	/** deregister one relation between the movable object and diva vm into the map "vm_MovableObject_Table" */
	void dereg_MovableObj_VM_relation(Ogre::MovableObject*,DIVA_VM*);

	void setParentNode(Ogre::SceneNode *parent) { _parentnode = parent ; } 
	Ogre::SceneNode * getParentNode() { return _parentnode ; }

	/** register a VM to listen to VMAnimation @default this event is not triggered for performacne reason */
	void addVMAnimationListener(DIVA_VM *);
	/** remove a VM from the listening list of VMAnimation */
	void removeVMAnimationListener(DIVA_VM *);

	/** called to trigger all the VMAnimation of VM which have registered */
	void triggerAllVMAnimation(const Ogre::FrameEvent& evt);

	/** the critical section lock to prevent race condition */
	void lock() ; 

	/** the critical section unlock to prevent race condition */
	void release();

	/** true to begin the triggering of VMAnimation()s, false to stop it */
	void setAnimationOnOff(bool b);

	
};
/*------------------------------------------------------------*/
#endif	//#ifndef _DIVA_Manager_H_
/*------------------------------------------------------------*/